package com.tanhua.dubbo.server.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.server.pojo.UserLike;
import com.tanhua.dubbo.server.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service(version = "1.0.0")
public class UserLikeApiImpl implements UserLikeApi {
    @Autowired
    private MongoTemplate mongoTemplate;
    public static final String LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";//喜欢key 前置字符串
    public static final String NOT_LIKE_REDIS_KEY_PREFIX = "USER_NOT_LIKE_";//不喜欢Key 前置字符串
  @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean likeUser(Long userId, Long likeUserId) {
        //判断该用户是否已经喜欢过,已经喜欢过就直接返回
        if (this.isLike(userId, likeUserId)) {
            return false;
        }
        //还没有标记喜欢  那就标记为喜欢存到数据库里面
        UserLike userLike = new UserLike();
        userLike.setId(ObjectId.get());
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setCreated(System.currentTimeMillis());
        //将数据存储到mongodb
        this.mongoTemplate.save(userLike);
//用户的喜欢数据保存到redis中
        //存储结构  大key   key-->USER_LIKE_1,  value-->2,"1"  就要构建大Key
        String redisKey = this.getLikeRedisKey(userId);  //大Key
        String hashKey = String.valueOf(likeUserId); //小Key
        //数据存储到reids
        this.redisTemplate.opsForHash().put(redisKey, hashKey, "1");
//因为这是喜欢列表 要是在不喜欢中 那么不喜欢就要删除数据
        //跟喜欢的一样 也要构建key
        if (this.notLikeUser(userId, likeUserId)) {
            String notRedisKey = this.getNotLikeRedisKey(userId);
            String notHashKey = String.valueOf(likeUserId);
            this.redisTemplate.opsForHash().delete(notHashKey, notHashKey);
        }
        return true;
    }

    /**
     * 是否喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    public Boolean isLike(Long userId, Long likeUserId) {
        String redisKey = this.getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        Boolean bool = this.redisTemplate.opsForHash().hasKey(redisKey, hashKey);
        return bool;
    }

    /**
     * 不喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean notLikeUser(Long userId, Long likeUserId) {
        //先判断是否已经不喜欢 ,要是是就直接返回
        if (this.isNotLike(userId, likeUserId)) {
            return false;
        }
        //第一次不喜欢  将数据保存到不喜欢表中  不用保存数据 就直接做个记录
        String reidsKey = this.getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        this.redisTemplate.opsForHash().put(reidsKey, hashKey, "1");
        //判断用户是否在喜欢表中
        if (this.isLike(userId, likeUserId)) {
            //删除mongodb中的数据
            //删除条件
            Query query = Query.query(Criteria.where("userId").is(userId).and("likeUserId").is(likeUserId));
            this.mongoTemplate.remove(query, UserLike.class);
            //删除redis中的数据
            String reidsKey1 = this.getLikeRedisKey(userId);
            String hashKey1 = String.valueOf(likeUserId);
            this.redisTemplate.opsForHash().delete(reidsKey1, hashKey1);
        }
        return true;
    }

    /**
     * 不喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    public Boolean isNotLike(Long userId, Long likeUserId) {
        String reidsKey = this.getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        return this.redisTemplate.opsForHash().hasKey(reidsKey, hashKey);
    }

    /**
     * 是否相互喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean isMutualLike(Long userId, Long likeUserId) {
        //只需要相互判断是否在自己喜欢的表中
        Boolean like1 = this.isLike(userId, likeUserId);
        Boolean like2 = this.isLike(likeUserId, userId);
//        if(like1&&like2){
//            return true;
//        }
//        return false;
        return like1 && like2;
    }

    /**
     * 查询喜欢列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> queryLikeList(Long userId) {
        //直接去数据库里面查询
        String redisKey = this.getLikeRedisKey(userId);
        Set<Object> keys = this.redisTemplate.opsForHash().keys(redisKey);
        if (CollUtil.isEmpty(keys)) {
            //没有数据 返回一个空集合
            return ListUtil.empty();
        }
        //查询到数据
        List<Long> result = new ArrayList<>(keys.size());
        for (Object key : keys) {
            result.add(Convert.toLong(key));
        }
        return result;
    }

    /**
     * 查询不喜欢列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> queryNotLikeList(Long userId) {
        String reidsKey = this.getNotLikeRedisKey(userId);
        Set<Object> keys = this.redisTemplate.opsForHash().keys(reidsKey);
        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }
        //创建一个集合来装这个查出的数据
        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;
    }

    private String getLikeRedisKey(Long userId) {
        return LIKE_REDIS_KEY_PREFIX + userId;
    }

    private String getNotLikeRedisKey(Long userId) {
        return NOT_LIKE_REDIS_KEY_PREFIX + userId;
    }

    /**
     * 相互喜欢的数量
     *
     * @return
     */
    @Override
    public Long queryMutualLikeCount(Long userId) {
        //实现2种方式：第一种：查询redis，第二种：查询MongoDB
        // 建议：优先使用redis查询，其次考虑使用Mongodb
        //先去查询用户喜欢的人
        List<Long> queryLikeList = this.queryLikeList(userId);
        long count = 0;
        //再去查询这些用户有哪些喜欢我的
        for (Long likeUserId : queryLikeList) {
            String likeRedisKey = this.getLikeRedisKey(likeUserId);
            String hashKey = String.valueOf(userId);
            //遍历   查询我喜欢的人里面有人喜欢我不
            Boolean bool = this.redisTemplate.opsForHash().hasKey(likeRedisKey, hashKey);
            if (bool) {
                count++;
            }
        }
        return count;
    }

    /**
     * 喜欢数
     *
     * @return
     */
    @Override
    public Long queryLikeCount(Long userId) {
        String likeRedisKey = this.getLikeRedisKey(userId);
        Set<Object> keys = this.redisTemplate.opsForHash().keys(likeRedisKey);
        return Long.valueOf(keys.size());
    }

    /**
     * 粉丝数
     *
     * @return
     */
    @Override
    public Long queryFanCount(Long userId) {
        //无法通过redis查询完成，必须从Mongodb中查询  ???  因为redis存取的是map集合 而userId的Key是在小key 里面 所以查不到
//查询条件
        Query query = Query.query(Criteria.where("userId").is(userId));
        long count = this.mongoTemplate.count(query, UserLike.class);
        return count;
    }

    /**
     * 查询相互喜欢列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<UserLike> queryMutualLikeList(Long userId, Integer page, Integer pageSize) {
        //查询我喜欢的列表
        List<Long> userLikeList = this.queryLikeList(userId);
        //查询喜欢我的人
        Query query = Query.query(Criteria.where("userId").in(userLikeList).and("likeUserId").is(userId));
        return this.queryList(query, page, pageSize);
    }

    /**
     * 查询我喜欢的列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<UserLike> queryLikeList(Long userId, Integer page, Integer pageSize) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        this.queryList(query,page,pageSize);
        return null;
    }

    /**
     * 查询粉丝列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<UserLike> queryFanList(Long userId, Integer page, Integer pageSize) {
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        return  this.queryList(query,page,pageSize);
    }

    private PageInfo<UserLike> queryList(Query query, Integer page, Integer pageSize) {
        //query是查询条件
        //设置分页
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        query.with(pageRequest);//让查询结果按时间排序
        List<UserLike> userLikeList = this.mongoTemplate.find(query, UserLike.class);
        PageInfo<UserLike> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(userLikeList);
        return  pageInfo;
    }

}
